package com.feishu.rpc.http;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSONObject;
import com.feishu.base.dto.HttpClientTokenDTO;
import com.feishu.base.dto.entity.ExecutionTypeDO;
import com.feishu.base.type.AttributesInterfaceType;
import com.feishu.base.type.ClassificationTypeEnum;
import com.feishu.base.type.OutJsonTypeEnum;
import com.feishu.json.factory.ConstructionOutJsonFactory;
import com.feishu.rpc.http.service.RemoteProcedureCallService;
import com.feishu.rpc.http.service.RemoteProcedureChangeCallService;
import com.feishu.rpc.http.service.RemoteProcedureNodeCallService;
import com.feishu.rpc.http.token.TokenWrapper;
import com.feishu.rpc.utils.HttpMethodEnum;
import com.hustcad.plm.pdm.flowbusiness.model.entity.FlowObject;
import com.hustcad.plm.pdm.partbom.vo.PartDetailsVO;
import com.ty.basic.exception.message.SystemErrorCodeEnum;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 实际网络发送
 */
@Service
public class RemoteHttpClient {
    private ConstructionOutJsonFactory constructionOutJsonFactory;
    private TokenWrapper tokenWrapper=new TokenWrapper();
    private RemoteSocketWrapper remoteSocketWrapper=new RemoteSocketWrapper();

    public JSONObject RemoteHttpToServer(OutJsonTypeEnum outJsonTypeEnum, ClassificationTypeEnum classificationTypeEnum, PartDetailsVO partDetails, ExecutionTypeDO executionTypeDO, Map<String,Object> outMap, FlowObject flowObject, Object parameter)throws Exception{
        JSONObject httpResult = new JSONObject();
        if(constructionOutJsonFactory==null){
            constructionOutJsonFactory=new ConstructionOutJsonFactory();
        }
        if(constructionOutJsonFactory==null){
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("JSON构造工具加载失败");
        }

        String uri= executionTypeDO.getUri();
        String method= executionTypeDO.getMethod();
        String protocol= executionTypeDO.getProtocol();
        String port= executionTypeDO.getPort();
        String home= executionTypeDO.getHome();

        try {
            Map<String, RemoteProcedureCallService> remoteProcedureCallServices=SpringUtil.getBeansOfType(RemoteProcedureCallService.class);
            RemoteProcedureCallService remoteProcedureCallService=null;
            for(Map.Entry<String,RemoteProcedureCallService> entity: remoteProcedureCallServices.entrySet()){
                AttributesInterfaceType attributesInterfaceType=entity.getValue().getClass().getAnnotation(AttributesInterfaceType.class);
                if(attributesInterfaceType.typeValue().equals(outJsonTypeEnum.value()) && attributesInterfaceType.classificationValue().equals(classificationTypeEnum.value())){
                    remoteProcedureCallService=entity.getValue();
                    break;
                }
            }

            HttpClientTokenDTO httpClientTokenDTO=tokenWrapper.getTokenDTOMap().get(outJsonTypeEnum.value());
            if(httpClientTokenDTO==null|| httpClientTokenDTO.getAuthorization()==null){
                if(remoteProcedureCallService!=null){
                    Object authorizationEntity=remoteProcedureCallService.getAuthorizationEntity();
                    httpClientTokenDTO = remoteProcedureCallService.getToken(authorizationEntity,executionTypeDO);
                    remoteProcedureCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                    tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                }
            }

            if(httpClientTokenDTO!=null && httpClientTokenDTO.getAuthorization()!=null){

                if("post".equals(method)){
                    remoteProcedureCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);

                    Map<String,Object> outParameter=remoteProcedureCallService.sendBefore(httpClientTokenDTO,outMap,executionTypeDO,flowObject,parameter);
                    if(outParameter==null){
                        outParameter=outMap;
                    }
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(home);
                    if("80".equals(port)==false){
                        stringBuilder.append(":");
                        stringBuilder.append(port);
                    }
                    stringBuilder.append(uri);

                    if("https".equals(protocol)){
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO, HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter, httpClientTokenDTO, null, remoteProcedureCallService);
                    }
                    else{
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                    }

                    if(remoteProcedureCallService.needReGetToken(httpResult,executionTypeDO)){
                        tokenWrapper.getTokenDTOMap().remove(outJsonTypeEnum.value());
                        Object authorizationEntity=remoteProcedureCallService.getAuthorizationEntity();
                        httpClientTokenDTO= remoteProcedureCallService.getToken(authorizationEntity,executionTypeDO);
                        remoteProcedureCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                        tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                        if("https".equals(protocol)){
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                        }
                        else{
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                        }
                    }
                    JSONObject outResultAfter = remoteProcedureCallService.sendAfter(httpResult,executionTypeDO,flowObject,parameter);
                    if(outResultAfter!=null){
                        httpResult=outResultAfter;
                    }
                    JSONObject outResult = remoteProcedureCallService.reconstructResult(httpResult,executionTypeDO);
                    if(outResult!=null){
                        httpResult=outResult;
                    }
                }
                return httpResult;
            }
            else{
                throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("授权获取失败");
            }
        }
        catch (Exception e){
            e.printStackTrace();
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException(e.getMessage());
        }
    }
    public JSONObject RemoteHttpChangeToServer(OutJsonTypeEnum outJsonTypeEnum, ClassificationTypeEnum classificationTypeEnum, PartDetailsVO partDetails, ExecutionTypeDO executionTypeDO, Map<String,Object> outMap, FlowObject flowObject, Object parameter)throws Exception{
        JSONObject httpResult = new JSONObject();
        if(constructionOutJsonFactory==null){
            constructionOutJsonFactory=new ConstructionOutJsonFactory();
        }
        if(constructionOutJsonFactory==null){
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("JSON构造工具加载失败");
        }

        String uri= executionTypeDO.getUri();
        String method= executionTypeDO.getMethod();
        String protocol= executionTypeDO.getProtocol();
        String port= executionTypeDO.getPort();
        String home= executionTypeDO.getHome();

        try {
            Map<String, RemoteProcedureChangeCallService> remoteProcedureCallServices=SpringUtil.getBeansOfType(RemoteProcedureChangeCallService.class);
            RemoteProcedureChangeCallService remoteProcedureChangeCallService=null;
            for(Map.Entry<String,RemoteProcedureChangeCallService> entity: remoteProcedureCallServices.entrySet()){
                AttributesInterfaceType attributesInterfaceType=entity.getValue().getClass().getAnnotation(AttributesInterfaceType.class);
                if(attributesInterfaceType.typeValue().equals(outJsonTypeEnum.value()) && attributesInterfaceType.classificationValue().equals(classificationTypeEnum.value())){
                    remoteProcedureChangeCallService=entity.getValue();
                    break;
                }
            }

            HttpClientTokenDTO httpClientTokenDTO=tokenWrapper.getTokenDTOMap().get(outJsonTypeEnum.value());
            if(httpClientTokenDTO==null|| httpClientTokenDTO.getAuthorization()==null){
                if(remoteProcedureChangeCallService!=null){
                    Object authorizationEntity=remoteProcedureChangeCallService.getAuthorizationEntity();
                    httpClientTokenDTO = remoteProcedureChangeCallService.getToken(authorizationEntity,executionTypeDO);
                    remoteProcedureChangeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                    tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                }
            }

            if(httpClientTokenDTO!=null && httpClientTokenDTO.getAuthorization()!=null){

                if("post".equals(method)){
                    remoteProcedureChangeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);

                    Map<String,Object> outParameter=remoteProcedureChangeCallService.sendBefore(httpClientTokenDTO,outMap,executionTypeDO,flowObject,parameter);
                    if(outParameter==null){
                        outParameter=outMap;
                    }
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(home);
                    if("80".equals(port)==false){
                        stringBuilder.append(":");
                        stringBuilder.append(port);
                    }
                    stringBuilder.append(uri);

                    if("https".equals(protocol)){
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureChangeCallService);
                    }
                    else{
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureChangeCallService);
                    }

                    if(remoteProcedureChangeCallService.needReGetToken(httpResult,executionTypeDO)){
                        tokenWrapper.getTokenDTOMap().remove(outJsonTypeEnum.value());
                        Object authorizationEntity=remoteProcedureChangeCallService.getAuthorizationEntity();
                        httpClientTokenDTO= remoteProcedureChangeCallService.getToken(authorizationEntity,executionTypeDO);
                        remoteProcedureChangeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                        tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                        if("https".equals(protocol)){
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureChangeCallService);
                        }
                        else{
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureChangeCallService);
                        }
                    }
                    JSONObject outResultAfter = remoteProcedureChangeCallService.sendAfter(httpResult,executionTypeDO,flowObject,parameter);
                    if(outResultAfter!=null){
                        httpResult=outResultAfter;
                    }
                    JSONObject outResult = remoteProcedureChangeCallService.reconstructResult(httpResult,executionTypeDO);
                    if(outResult!=null){
                        httpResult=outResult;
                    }
                }
                return httpResult;
            }
            else{
                throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("授权获取失败");
            }
        }
        catch (Exception e){
            e.printStackTrace();
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException(e.getMessage());
        }
    }
    public JSONObject selectUserDataToServer(OutJsonTypeEnum outJsonTypeEnum, ClassificationTypeEnum classificationTypeEnum, PartDetailsVO partDetails, ExecutionTypeDO executionTypeDO, Map<String,Object> outMap)throws Exception{
        JSONObject httpResult = new JSONObject();
        if(constructionOutJsonFactory==null){
            constructionOutJsonFactory=new ConstructionOutJsonFactory();
        }
        if(constructionOutJsonFactory==null){
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("JSON构造工具加载失败");
        }

        String uri= executionTypeDO.getUri();
        String method= executionTypeDO.getMethod();
        String protocol= executionTypeDO.getProtocol();
        String port= executionTypeDO.getPort();
        String home= executionTypeDO.getHome();

        try {
            Map<String,RemoteProcedureCallService> remoteProcedureCallServices=SpringUtil.getBeansOfType(RemoteProcedureCallService.class);
            RemoteProcedureCallService remoteProcedureCallService=null;
            for(Map.Entry<String,RemoteProcedureCallService> entity: remoteProcedureCallServices.entrySet()){
                AttributesInterfaceType attributesInterfaceType=entity.getValue().getClass().getAnnotation(AttributesInterfaceType.class);
                if(attributesInterfaceType.typeValue().equals(outJsonTypeEnum.value()) && attributesInterfaceType.classificationValue().equals(classificationTypeEnum.value())){
                    remoteProcedureCallService=entity.getValue();
                    break;
                }
            }

            HttpClientTokenDTO httpClientTokenDTO=tokenWrapper.getTokenDTOMap().get(outJsonTypeEnum.value());
            if(httpClientTokenDTO==null|| httpClientTokenDTO.getAuthorization()==null){
                if(remoteProcedureCallService!=null){
                    Object authorizationEntity=remoteProcedureCallService.getAuthorizationEntity();
                    httpClientTokenDTO = remoteProcedureCallService.getToken(authorizationEntity,executionTypeDO);
                    remoteProcedureCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,null,null);
                    tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                }
            }

            if(httpClientTokenDTO!=null && httpClientTokenDTO.getAuthorization()!=null){

                if("post".equals(method)){
                    Map<String,Object> outParameter=outMap;
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(home);
                    if("80".equals(port)==false){
                        stringBuilder.append(":");
                        stringBuilder.append(port);
                    }
                    stringBuilder.append(uri);

                    if("https".equals(protocol)){
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                    }
                    else{
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                    }
                    if(httpResult.getLongValue("code")==99991663){
                        tokenWrapper.getTokenDTOMap().remove(outJsonTypeEnum.value());
                        Object authorizationEntity=remoteProcedureCallService.getAuthorizationEntity();
                        httpClientTokenDTO= remoteProcedureCallService.getToken(authorizationEntity,executionTypeDO);
                        remoteProcedureCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,null,null);
                        tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                        if("https".equals(protocol)){
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                        }
                        else{
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureCallService);
                        }
                    }

                    JSONObject outResultAfter = remoteProcedureCallService.sendAfter(httpResult,executionTypeDO,null,null);
                    if(outResultAfter!=null){
                        httpResult=outResultAfter;
                    }
                    JSONObject outResult = remoteProcedureCallService.reconstructResult(httpResult,executionTypeDO);
                    if(outResult!=null){
                        httpResult=outResult;
                    }
                }
                return httpResult;
            }
            else{
                throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("授权获取失败");
            }
        }
        catch (Exception e){
            e.printStackTrace();
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException(e.getMessage());
        }
    }
    public JSONObject RemoteHttpNodeToServer(OutJsonTypeEnum outJsonTypeEnum, ClassificationTypeEnum classificationTypeEnum, PartDetailsVO partDetails, ExecutionTypeDO executionTypeDO, Map<String,Object> outMap, FlowObject flowObject, Object parameter)throws Exception{
        JSONObject httpResult = new JSONObject();
        if(constructionOutJsonFactory==null){
            constructionOutJsonFactory=new ConstructionOutJsonFactory();
        }
        if(constructionOutJsonFactory==null){
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("JSON构造工具加载失败");
        }

        String uri= executionTypeDO.getUri();
        String method= executionTypeDO.getMethod();
        String protocol= executionTypeDO.getProtocol();
        String port= executionTypeDO.getPort();
        String home= executionTypeDO.getHome();

        try {
            Map<String, RemoteProcedureNodeCallService> remoteProcedureNodeCallServiceMap=SpringUtil.getBeansOfType(RemoteProcedureNodeCallService.class);
            RemoteProcedureNodeCallService remoteProcedureNodeCallService=null;
            for(Map.Entry<String,RemoteProcedureNodeCallService> entity: remoteProcedureNodeCallServiceMap.entrySet()){
                AttributesInterfaceType attributesInterfaceType=entity.getValue().getClass().getAnnotation(AttributesInterfaceType.class);
                if(attributesInterfaceType.typeValue().equals(outJsonTypeEnum.value()) && attributesInterfaceType.classificationValue().equals(classificationTypeEnum.value())){
                    remoteProcedureNodeCallService=entity.getValue();
                    break;
                }
            }

            HttpClientTokenDTO httpClientTokenDTO=tokenWrapper.getTokenDTOMap().get(outJsonTypeEnum.value());
            if(httpClientTokenDTO==null|| httpClientTokenDTO.getAuthorization()==null){
                if(remoteProcedureNodeCallService!=null){
                    Object authorizationEntity=remoteProcedureNodeCallService.getAuthorizationEntity();
                    httpClientTokenDTO = remoteProcedureNodeCallService.getToken(authorizationEntity,executionTypeDO);
                    remoteProcedureNodeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                    tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                }
            }

            if(httpClientTokenDTO!=null && httpClientTokenDTO.getAuthorization()!=null){

                if("post".equals(method)){
                    remoteProcedureNodeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);

                    Map<String,Object> outParameter=remoteProcedureNodeCallService.sendBefore(httpClientTokenDTO,outMap,executionTypeDO,flowObject,parameter);
                    if(outParameter==null){
                        outParameter=outMap;
                    }
                    StringBuilder stringBuilder = new StringBuilder();
                    stringBuilder.append(home);
                    if("80".equals(port)==false){
                        stringBuilder.append(":");
                        stringBuilder.append(port);
                    }
                    stringBuilder.append(uri);

                    if("https".equals(protocol)){
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureNodeCallService);
                    }
                    else{
                        httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureNodeCallService);
                    }

                    if(remoteProcedureNodeCallService.needReGetToken(httpResult,executionTypeDO)){
                        tokenWrapper.getTokenDTOMap().remove(outJsonTypeEnum.value());
                        Object authorizationEntity=remoteProcedureNodeCallService.getAuthorizationEntity();
                        httpClientTokenDTO= remoteProcedureNodeCallService.getToken(authorizationEntity,executionTypeDO);
                        remoteProcedureNodeCallService.setParameter(httpClientTokenDTO,partDetails,executionTypeDO,flowObject,parameter);
                        tokenWrapper.getTokenDTOMap().put(outJsonTypeEnum.value(),httpClientTokenDTO);
                        if("https".equals(protocol)){
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTPS, stringBuilder.toString(), outParameter,httpClientTokenDTO,null,remoteProcedureNodeCallService);
                        }
                        else{
                            httpResult = remoteSocketWrapper.httpPostMethodToJSONObject(executionTypeDO,HttpMethodEnum.HTTP,stringBuilder.toString(),outParameter,httpClientTokenDTO,null,remoteProcedureNodeCallService);
                        }
                    }
                    JSONObject outResultAfter = remoteProcedureNodeCallService.sendAfter(httpResult,executionTypeDO,flowObject,parameter);
                    if(outResultAfter!=null){
                        httpResult=outResultAfter;
                    }
                    JSONObject outResult = remoteProcedureNodeCallService.reconstructResult(httpResult,executionTypeDO);
                    if(outResult!=null){
                        httpResult=outResult;
                    }
                }
                return httpResult;
            }
            else{
                throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException("授权获取失败");
            }
        }
        catch (Exception e){
            e.printStackTrace();
            throw SystemErrorCodeEnum.WORK_FLOW_CONTENT_ERROR.getException(e.getMessage());
        }
    }

}
